﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using FXnaInfrastructure;

namespace GWModflow.FileLayers.MT3DMS
{
    /// <summary>
    /// 化学反应子程序包的输入在主程序中预设的单位INRCT=8上读取
    /// </summary>
    public class ChemicalReactionPack:Package
    {
        public ChemicalReactionPack()
        {
            this._fileType = FileType.RCT;
            this.Fname = "mt3dms.rct";
        }
        private int _ISOTHM;//标示模拟的吸附(或双区域质量运移)的种类
        /// <summary>
        /// 标示模拟的吸附(或双区域质量运移)的种类
        /// =0,不模拟吸附
        ///  =1,线性等温(平衡控制)
        ///   =2,Freundlich等温(平衡控制)
        ///   =3,朗缪尔等温(平衡控制)
        ///   =4,一阶动力吸附(不平衡)
        ///   =5,双区域质量运移(没有吸附)
        ///   =6,双区域质量运移(带吸附)
        /// </summary>
        public int ISOTHM
        {
            get { return _ISOTHM; }
            set { _ISOTHM = value; }
        }
        private int _IREACT;//标示模拟的动力速率反应的种类
        /// <summary>
        /// 标示模拟的动力速率反应的种类
        /// =0,不模拟动力速率反应
        /// =1,一阶不可逆反应
        /// </summary>
        public int IREACT
        {
            get { return _IREACT; }
            set { _IREACT = value; }
        }
        private int _IRCTOP;//标示反应变量的输入方法:
        /// <summary>
        /// 标示反应变量的输入方法:
        /// >=2,所有反应变量在逐一单元的基础上定义为三维数组
        /// 小于2,所有反应变量定义为一维数组,其中每个数组数值对应单个的一层.这个选项旨在保持与前几版本MT3D的兼容性
        /// </summary>
        public int IRCTOP
        {
            get { return _IRCTOP; }
            set { _IRCTOP = value; }
        }
        private int _IGETSC;//在模拟不平衡吸附(ISOTHM=4)或双区域质量运移(ISOTHM=5或6)时标示是否读取所有物种不平衡吸附或不移动状态的初始浓度的整数标识
        /// <summary>
        /// 在模拟不平衡吸附(ISOTHM=4)或双区域质量运移(ISOTHM=5或6)时标示是否读取所有物种不平衡吸附
        /// 或不移动状态的初始浓度的整数标识
        /// =0,吸附或不移动状态的初始浓度不被读取.程序默认吸附状态与溶解状态(ISOTHM=4)平衡,不移动区域的浓度为零(ISTHM=5或6)
        /// >0,读取所有物种在吸附状态或不移动液体状态的初始浓度
        /// </summary>
        public int IGETSC
        {
            get { return _IGETSC; }
            set { _IGETSC = value; }
        }
        private List<double[,]> _RHOB=new List<double[,]> ();//(如果ISOTHM=1,2,3,4或6,但不是5时,输入),是含水层介质的块密度(单位ML^-3)
        /// <summary>
        /// (如果ISOTHM=1,2,3,4或6,但不是5时,输入),
        /// 是含水层介质的块密度(单位ML^-3)
        /// </summary>
        public  List<double[,]> RHOB
        {
            get { return _RHOB; }
            set { _RHOB = value; }
        }


        private List<double[,]> _PRSITY2=new List<double[,]> ();  //(如果ISOTHM=5或6,输入)是不移动区域的多孔性,即当模拟双区域系统时充满不移动流体的空体积与含水层介质的块体积的比值

        /// <summary>
        /// (如果ISOTHM=5或6,输入)
        /// 是不移动区域的多孔性,即当模拟双区域系统时充满不移动流体的空体积与含水层介质的块体积的比值
        /// </summary>
        public List<double[,]> PRSITY2
        {
            get { return _PRSITY2; }
            set { _PRSITY2 = value; }
        }

        private List<List<double[,]>> _SRCONC=new List<List<double[,]>> ();//(对于每个物种,如果IGETSC>0,输入)
        /// <summary>
        /// (对于每个物种,如果IGETSC>0,输入)
        /// 当ISOTHM=4时,用户指定的特定物种在吸附状态的初始浓度(单位,MM^-1).
        /// 注意对于平衡控制的吸附,吸附状态的初始浓度不能被指定
        /// ISOTHM=5或6时,用户指定的不移动液体状态的初始浓度(单位ML^-3)
        /// </summary>
        public  List<List<double[,]>> SRCONC
        {
            get { return _SRCONC; }
            set { _SRCONC = value; }
        }
      
        private List<List<double[,]>> _SP1=new List<List<double[,]>> ();//(对于每个物种,如果ISOTHM>0,输入)
        /// <summary>
        /// (对于每个物种,如果ISOTHM>0,输入)
        /// 第一吸附参数.SP1的使用取决于选择的吸附种类(即ISOTHM的值)
        /// 对于线性吸附(ISOTHM=1)和不平衡吸附(ISOTHM=4),SP1是分布系数(Kd)(单位L^3M^-1)
        /// 对于Freundlich吸附(ISOTHM=2),SP1是Freundlich平衡常数(Kf)(单位取决于Freundlich指数)
        /// 对于朗缪尔吸附(ISOTHM=3),SP1是朗缪尔平衡常数(Kl)(单位L3M-1).
        /// 对于没有吸附的双区域质量运移(ISOTHM=5),SP1不被使用但仍然需要输入
        /// 对于带有吸附的双区域质量运移(ISOTHM=6),SP1也是分布系数(Kd)(单位L^3M^-1)
        /// </summary>
        public  List<List<double[,]>> SP1
        {
            get { return _SP1; }
            set { _SP1 = value; }
        }



        private List<List<double[,]>> _SP2=new List<List<double[,]>> ();//(对于每个物种,如果ISOTHM>0,输入)
        /// <summary>
        /// (对于每个物种,如果ISOTHM>0,输入)
        /// 第二吸附或双区域模型参数.SP2的使用取决于选择的吸附种类或双区域模型
        /// 对于线性吸附(ISOTHM=1),读取但不适用SP2
        /// 对于Freundlich吸附(ISOTHM=2),SP2是Freundlich指数.
        /// 对于朗缪尔吸附(ISOTHM=3),SP2可利用吸附处(S)的总浓度(单位MM^-1)
        /// 对于不平衡吸附(ISOTHM=4),SP2是溶解和吸附状态间的一阶质量运移率(单位T^-1)
        /// 对于双区域质量运移(ISOTHM=5或6),SP2是两个区域间一阶质量运移率(单位T^-1)
        /// </summary>
        public  List<List<double[,]>> SP2
        {
            get { return _SP2; }
            set { _SP2 = value; }
        }



        private List<List<double[,]>> _RC1=new List<List<double[,]>> ();//(对于每个物种,如果IREACT>0,输入)
        /// <summary>
        /// (对于每个物种,如果IREACT>0,输入)
        /// 溶解(液体)状态的一阶反应率(单位T^-1).如果模拟一个双区域系统,假设液体状态的反应率在移动和不移动区域相等
        /// </summary>
        public  List<List<double[,]>> RC1
        {
            get { return _RC1; }
            set { _RC1 = value; }
        }


        private List<List<double[,]>> _RC2=new List<List<double[,]>> ();//(对于每个物种,如果IREACT>0,输入)
        /// <summary>
        /// (对于每个物种,如果IREACT>0,输入)
        /// 吸附状态的一阶反应率(单位T^-1).
        /// 如果模拟一个双区域系统,假设吸附状态的反应率在移动和不移动区域相等.
        /// 一般来说,如果反应是放射性衰退的,RC2应被设置等同于RC1,而对于生物递降分解,RC2可以不同于RC1
        /// 注意如果模拟中不包含吸附,RC2被读取但不被使用
        /// </summary>
        public  List<List<double[,]>> RC2
        {
            get { return _RC2; }
            set { _RC2 = value; }
        }
      
      
        public override void WriteFile(string path)
        {
            string content = string.Format("{0,10}",GetNumberLengthFormat ( this.ISOTHM,10))  + string.Format("{0,10}",GetNumberLengthFormat ( this.IREACT,10))  + string.Format("{0,10}",GetNumberLengthFormat ( this.IRCTOP,10))  +
                string.Format("{0,10}",GetNumberLengthFormat ( this.IGETSC,10))  + "          ISOTHM,IREACT,IRCTOP,IGETSC" + "\r\n";
            string str = "";
            if (this.ISOTHM == 1 || this.ISOTHM == 2 || this.ISOTHM == 3 || this.ISOTHM == 4 || this.ISOTHM == 6 && this.ISOTHM != 5)
            {
                for (int i = 0; i < this.RHOB.Count; i++)
                {
                    if (IsConstant(this.RHOB[i]))
                    {
                        content += string.Format("{0,10}",GetNumberLengthFormat ( 0,10))  + string.Format("{0,10}",GetNumberLengthFormat ( this.RHOB[i][0, 0],10)) + "       RHOB" + "\r\n";
                    }
                    else
                    {
                        GetArrayString(this.RHOB[i], ref str);
                       
                        content += str;
                    }
                }
            }

            if (this.ISOTHM == 5 || this.ISOTHM == 6)
            {
                for (int i = 0; i < this.PRSITY2.Count; i++)
                {
                    if (IsConstant(this.PRSITY2[i]))
                    {
                        content += string.Format("{0,10}", GetNumberLengthFormat (0,10))  + string.Format("{0,10}",GetNumberLengthFormat ( this.PRSITY2[i][0, 0],10)) + "       PRSITY2" + "\r\n";
                    }
                    else
                    {
                        GetArrayString(this.PRSITY2[i], ref str);
                    
                        content += str;
                    }
                }
            }

            if (this.IGETSC > 0)
            {
                for (int i = 0; i < this.SRCONC.Count; i++)
                {
                    for (int j = 0; j < this.SRCONC[i].Count; j++)
                    {
                        if (IsConstant(this.SRCONC[i][j]))
                        {
                            content += string.Format("{0,10}",GetNumberLengthFormat ( 0,10)) + string.Format("{0,10}",GetNumberLengthFormat ( this.SRCONC[i][j][0, 0],10)) + "       SRCONC" + "\r\n";
                        }
                        else
                        {
                            GetArrayString(this.SRCONC[i][j], ref str);
                         
                            content += str;
                        }
                    }
                }
            }
            if (this.ISOTHM > 0)
            {
                for (int i = 0; i < this.SP1.Count; i++)
                {
                    for (int j = 0; j < this.SP1[i].Count; j++)
                    {
                        if (IsConstant(this.SP1[i][j]))
                        {
                            content += string.Format("{0,10}",GetNumberLengthFormat ( 0,10))  + string.Format("{0,10}",GetNumberLengthFormat ( this.SP1[i][j][0, 0],10)) + "       SP1" + "\r\n";
                        }
                        else
                        {
                            GetArrayString(this.SP1[i][j], ref str);
                         
                            content += str;
                        }
                    }
                }
            }

            if (this.ISOTHM > 0)
            {
                for (int i = 0; i < this.SP2.Count; i++)
                {
                    for (int j = 0; j < this.SP2[i].Count; j++)
                    {
                        if (IsConstant(this.SP2[i][j]))
                        {
                            content += string.Format("{0,10}", GetNumberLengthFormat(0, 10)) + string.Format("{0,10}", GetNumberLengthFormat(this.SP2[i][j][0,0], 10)) + "       SP2" + "\r\n";
                        }
                        else
                        {
                            GetArrayString(this.SP2[i][j], ref str);
                           
                            content += str;
                        }
                    }
                }
            }
            if (this.IREACT > 0)
            {
                for (int i = 0; i < this.RC1.Count; i++)
                {
                    for (int j = 0; j < this.RC1[i].Count; j++)
                    {
                        if (IsConstant(this.RC1[i][j]))
                        {
                            content += string.Format("{0,10}", GetNumberLengthFormat(0, 10)) + string.Format("{0,10}", GetNumberLengthFormat(this.RC1[i][j][0, 0], 10)) + "       RC1" + "\r\n";
                        }
                        else
                        {
                            GetArrayString(this.RC1[i][j], ref str);
                          
                            content += str;
                        }
                    }
                }
            }
            if (this.IREACT > 0)
            {
                for (int i = 0; i < this.RC2.Count; i++)
                {
                    for (int j = 0; j < this.RC2[i].Count; j++)
                    {
                        if (IsConstant(this.RC2[i][j]))
                        {
                            content += string.Format("{0,10}",GetNumberLengthFormat( 0,10))  + string.Format("{0,10}", GetNumberLengthFormat(this.RC2[i][j][0, 0],10)) + "       RC2" + "\r\n";
                        }
                        else
                        {
                            GetArrayString(this.RC2[i][j], ref str);
                           
                            content += str;
                        }
                    }
                }
            }

            string fname = path + this.Fname;
            FileHelper.WriteFile(fname, content);
        }
    }
}
